home *** CD-ROM | disk | FTP | other *** search
- /*
- DU_LIB v2
- Gem Window Management & Dialog Library For Lattice C
- ©1994,1995 by Craig Graham.
-
- Based on the DU_LIBv1 Library for HiSoft Basic.
- */
-
- /*
- Text Edit Widget
-
- This provides a full text editor with scrolling & mouse click/drag selection
- and GEM clipboard support. If the cut & paste routines look a little inefficient,
- it's because they are intended to allow external access to the cut paste functions
- as well as the standard keyboard shortcuts (^X,^C,^V).
- */
-
- #include "DULIB.H"
- #include <stdio.h>
-
- /* Create a text widget */
- void Set_text_widget(short dialog, short ob, short max_columns, short max_lines)
- {
- text_line *tln_t;
- Elist *n;
-
- Set_object_Kcallback(dialog, ob, &TW_keypress); // Install Object Layer keyhandler
- Set_object_callback(dialog, ob, &TW_mouse_click); // Install a callback to handle mouse clicks
- Set_object_redraw(dialog, ob, &TW_display); // Setup a redraw function
-
- if (find_event(dialog,ob,&n)) // There be an event structure for the widget by now - if there isn't then we've got problems
- {
- n->wtext.max_lines=max_lines;
- n->wtext.max_columns=max_columns;
- n->wtext.current_column=0;
- n->wtext.cursor_y=0;
-
- tln_t=(text_line*)malloc(sizeof(text_line)); // Create initial line
- tln_t->the_text=(char*)malloc(sizeof(char)*max_columns);
- tln_t->the_text[0]='\0';
- tln_t->eof_line=0; // initially nothing on the line
- tln_t->prev=NULL; // No lines before this
- tln_t->next=NULL; // No lines after this
-
- n->wtext.current_line=tln_t; // Initial cursor position == top line.
- n->wtext.display_baseline=tln_t; // Initial display baseline == top line.
- n->wtext.sel_start_line=n->wtext.sel_end_line=NULL; // Initially, no text selected
-
- }else{
- form_alert(1,"[1][ ERROR: Unable to create text widget. ][ Bugger ]");
- }
- }
-
- /*
- Change/initialise all the text in a text widget
- This allows you to load text into a text widget.
- */
- void Change_widget_text(short dialog, short ob, char *t[], short lines)
- {
- Elist *n;
- text_line *tln, *tln_t;
- short sl,l,max_columns;
-
- if (find_event(dialog,ob,&n))
- {
- tln=n->wtext.text; // Dispose of the current text widget contents
- while(tln) {
- tln_t=tln;
- tln=tln->next;
- free(tln_t->the_text); //free up the char array.
- free(tln_t); //free up the line structure
- }
- n->wtext.text=NULL;
- n->wtext.current_column=0;
- n->wtext.cursor_y=0;
- n->wtext.sel_start_line=n->wtext.sel_end_line=NULL; // No text selected
-
- if ((lines>n->wtext.max_lines)&&(n->wtext.max_lines>0))
- {
- lines=n->wtext.max_lines;
- }
-
- max_columns=n->wtext.max_columns;
- for (l=0; l<lines; l++) // Find the maximum number of columns used
- {
- sl=strlen(t[l]);
- if (sl>max_columns) max_columns=sl;
- }
- max_columns++;
- n->wtext.max_columns=max_columns;
-
- tln_t=(text_line*)malloc(sizeof(text_line)); // Create initial line
- tln_t->the_text=(char*)malloc(sizeof(char)*max_columns);
- tln_t->the_text[0]='\0';
- tln_t->eof_line=0; // initially nothing on the line
- tln_t->prev=NULL; // No lines before this
-
- n->wtext.current_line=tln_t; // Initial cursor position == top line.
- n->wtext.display_baseline=tln_t; // Initial display baseline == top line.
-
- n->wtext.text=tln_t;
- for (l=0; l<lines; l++)
- {
- tln=tln_t;
-
- sprintf(tln->the_text,"%s",t[l]); // Copy the text into the line entry
- tln->eof_line=strlen(t[l]);
-
- tln_t=(text_line*)malloc(sizeof(text_line));
- tln_t->the_text=(char*)malloc(sizeof(char)*max_columns);
- tln->next=tln_t;
- tln_t->prev=tln;
- }
- free(tln_t); // Loop creates one to many entries :(
- tln->next=NULL;
-
- }else{
- form_alert(1,"[1][ ERROR: Cann't find text widget info. ][ Bugger ]");
- }
-
- }
-
- /*
- Get all the text in a text widget
- This will dispose of the current contents of a char *t[] array if text_lines
- is passed
- */
- short Get_widget_text(short dialog, short ob, char ***text, short text_lines)
- {
- Elist *n;
- text_line *tln;
- char **txt;
- short number_of_lines,l;
-
- if (find_event(dialog,ob,&n))
- {
- if (text_lines) // Dispose of current text
- {
- txt=*text;
- for(l=0; l<text_lines; l++) free(txt[l]);
- free(txt);
- }
-
- tln=n->wtext.text; // Count up the number of lines
- for(number_of_lines=0; tln; number_of_lines++) tln=tln->next;
-
- number_of_lines++;
-
- txt=(char**)malloc(sizeof(char*)*number_of_lines);
- *text=txt;
-
- l=0; tln=n->wtext.text;
-
- do {
- txt[l]=(char*)malloc(sizeof(char)*(tln->eof_line+1));
-
- sprintf(txt[l],"%s",tln->the_text);
-
- l++; tln=tln->next;
- } while (tln);
-
- return number_of_lines;
- }else{
- form_alert(1,"[1][ ERROR: Cann't find text widget info. ][ Bugger ]");
- }
- }
-
- /*
- Display the text cursor for a given text widget
- */
- void TW_display_cursor(short dialog, short ob)
- {
- Elist *n;
- short ch,cw;
- short pts[8];
- short dlx,dly;
-
- if (find_event(dialog,ob,&n))
- {
- vsf_color(x_handle,1); vsf_interior(x_handle,FIS_SOLID); vsf_perimeter(x_handle,0);
- vswr_mode(x_handle, MD_XOR);
-
- vqt_extent(x_handle,"A",pts);
- ch=abs(pts[1]-pts[7]); // Height of one character in current font
- cw=abs(pts[0]-pts[2]); // Width of one character in current font
-
- dlx=cr_clip.g_x+5+cw*n->wtext.current_column; dly=cr_clip.g_y+8+ch*n->wtext.cursor_y;
- pts[0]=dlx; pts[2]=dlx+cw-1;
- pts[1]=dly; pts[3]=dly+ch-1;
- v_bar(x_handle,pts);
- vswr_mode(x_handle, MD_REPLACE);
- }
- }
-
- /*
- Display a highlighted (ie. selected) region in a text
- widget.
- */
- void TW_display_highlighted(short dialog, short ob)
- {
- Elist *n;
- text_line *tln_t,*tl,*de_l,*ds_l;
- short ch,cw,l;
- short pts[8];
- short dlx,dly;
- short sx, sy, ex, ey;
-
- if (find_event(dialog,ob,&n))
- {
- vsf_color(x_handle,1); vsf_interior(x_handle,FIS_SOLID); vsf_perimeter(x_handle,0);
- vswr_mode(x_handle, MD_XOR);
-
- vqt_extent(x_handle,"A",pts);
- ch=abs(pts[1]-pts[7]); // Height of one character in current font
- cw=abs(pts[0]-pts[2]); // Width of one character in current font
-
- tl=n->wtext.display_baseline;
- ds_l=de_l=NULL;
- sy=ey=-1;
- for(l=0; (l<n->wtext.display_lines_high)&&(tl->next!=NULL); tl=tl->next )
- {
- if (tl==n->wtext.sel_start_line)
- {
- ds_l=tl;
- sx=n->wtext.sel_start_char;
- sy=l;
- }
- if (tl==n->wtext.sel_end_line)
- {
- de_l=tl;
- ex=n->wtext.sel_end_char;
- ey=l;
- }
- l++;
- }
-
- if (ds_l==NULL)
- {
- ds_l=n->wtext.display_baseline;
- sx=sy=0;
- }
- if (de_l==NULL)
- {
- de_l=tl;
- ex=tl->eof_line;
- ey=l-1;
- }
-
- if (sy==ey) // mark only on a single line
- {
- dlx=cr_clip.g_x+5+cw*sx; dly=cr_clip.g_y+8+ch*sy;
- pts[0]=dlx; pts[2]=dlx+cw*(ex-sx)-1;
- pts[1]=dly; pts[3]=dly+ch-1;
- v_bar(x_handle,pts);
- }else{ // mark split over two or more lines
- dlx=cr_clip.g_x+5+cw*sx; dly=cr_clip.g_y+8+ch*sy; // display last line (start_char .. end of line)
- pts[0]=dlx; pts[2]=dlx+cw*(ds_l->eof_line-sx)-1;
- pts[1]=dly; pts[3]=dly+ch-1;
- v_bar(x_handle,pts);
-
- tln_t=ds_l; // display middle bit (fully selected lines) - if any
- pts[0]=cr_clip.g_x+5;
- for(l=sy+1; l<ey; l++)
- {
- tln_t=tln_t->next;
- pts[2]=pts[0]+cw*tln_t->eof_line-1;
- pts[1]=cr_clip.g_y+8+ch*l;; pts[3]=pts[1]+ch-1;
- v_bar(x_handle,pts);
- }
-
- dlx=cr_clip.g_x+5; dly=cr_clip.g_y+8+ch*ey; // display last line (start of line .. end_char)
- pts[0]=dlx; pts[2]=dlx+cw*ex+1;
- pts[1]=dly; pts[3]=dly+ch-1;
- v_bar(x_handle,pts);
- }
- vswr_mode(x_handle, MD_REPLACE);
- }
- }
-
- /*
- Text Widget Display Routine
- */
- short TW_display(void)
- {
- Elist *n;
- char cursor[2];
- short de,l,ch,cw;
- short pts[8];
- short dlx,dly,f;
- text_line *tl;
-
- if (find_event(this_dialog,this_ob,&n))
- {
- vst_color(x_handle,1); vst_point(x_handle,10,&junk,&junk,&junk,&junk);
- vst_rotation(x_handle,0); vst_alignment(x_handle,0,0,wm_inv,wm_outv);
- vsf_interior(x_handle,FIS_SOLID); vsf_perimeter(x_handle,0);
- vswr_mode(x_handle, MD_TRANS);
-
- vsf_color(x_handle,0);
- pts[0]=cr_clip.g_x+1; pts[2]=pts[0]+cr_clip.g_w-2;
- pts[1]=cr_clip.g_y+1; pts[3]=pts[1]+cr_clip.g_h-2;
- v_bar(x_handle,pts);
- vsf_color(x_handle,1);
-
- vqt_extent(x_handle,"A",pts);
- ch=abs(pts[1]-pts[7]); // Height of one character in current font
- cw=abs(pts[0]-pts[2]); // Width of one character in current font
-
- cursor[1]='\0';
-
- n->wtext.display_lines_high=(short)(cr_clip.g_h/ch) - 1; // fill in this each time, just 'coz it's easy to calculate here
-
- de=cr_clip.g_y+cr_clip.g_h-5;
- tl=n->wtext.display_baseline;
-
- if (tl)
- {
- dlx=cr_clip.g_x+5; l=0;
- for(dly=cr_clip.g_y+ch+5; (dly<de)&&(tl!=NULL); dly=dly+ch)
- {
- v_gtext(x_handle, dlx, dly, tl->the_text); // display the text line
- tl=tl->next;
- }
- vswr_mode(x_handle, MD_XOR);
- dlx=cr_clip.g_x+5+cw*n->wtext.current_column; dly=cr_clip.g_y+8+ch*n->wtext.cursor_y;
- pts[0]=dlx; pts[2]=dlx+cw-1;
- pts[1]=dly; pts[3]=dly+ch-1;
- v_bar(x_handle,pts);
- vswr_mode(x_handle, MD_REPLACE);
- }
-
- /* Highlight any selected text which is currently displayed */
- if ((n->wtext.sel_start_line!=NULL)&&(n->wtext.sel_end_line!=NULL))
- {
- if ((n->wtext.sel_start_line!=n->wtext.sel_end_line)||(n->wtext.sel_start_char!=n->wtext.sel_end_char))
- {
- tl=n->wtext.display_baseline; f=FALSE;
- for(l=0; (l<n->wtext.display_lines_high)&&(tl->next!=NULL); tl=tl->next )
- {
- if ((tl==n->wtext.sel_start_line)||(tl==n->wtext.sel_end_line)) f=TRUE;
- l++;
- }
- if (!f) // No selection markers found in display at all, check to see if whole display is selected
- {
- tl=n->wtext.sel_start_line;
- for(l=0; (l<n->wtext.display_lines_high)&&(tl->next!=NULL); tl=tl->next )
- {
- if (tl==n->wtext.display_baseline) // If we find the display baseline in the selected text, then the whole display is selected
- f=TRUE;
- l++;
- }
- }
- if (f) TW_display_highlighted(this_dialog, this_ob);
- }
- }
- }else{
- form_alert(1,"[1][ ERROR: Cann't find text widget info. ][ Bugger ]");
- }
- return TRUE;
- }
-
- /*
- Text Widget mouse click handler
- */
- short TW_mouse_click(void)
- {
- Elist *n;
- text_line *tln_t,*tl;
- short ch,cw,x,y,rx,ry,l,mb,rl_x,rl_y,lrl_x,lrl_y,e;
- short f;
- short pts[8];
-
- graf_mkstate(&lrl_x,&lrl_y,&mb,&junk);
-
- if (find_event(this_dialog,this_ob,&n))
- {
- vqt_extent(x_handle,"A",pts);
- ch=abs(pts[1]-pts[7]); // Height of one character in current font
- cw=abs(pts[0]-pts[2]); // Width of one character in current font
- x=(short)((cr_mx-5/2)/cw); // Click position in terms of characters & lines
- y=(short)((cr_my-5)/ch); if (y<0) y=0;
-
- if (mb==0)
- {
- graf_mouse(M_OFF,NULL); // Un-display the old cursor
- TW_display_cursor(this_dialog, this_ob);
-
- n->wtext.current_line=n->wtext.display_baseline;
- for(l=0; (n->wtext.current_line->next!=NULL)&&(l<y); l++)
- n->wtext.current_line=n->wtext.current_line->next;
-
- n->wtext.cursor_y=l;
-
- if (x>n->wtext.current_line->eof_line)
- n->wtext.current_column=n->wtext.current_line->eof_line;
- else
- n->wtext.current_column=x;
-
- TW_display_cursor(this_dialog, this_ob); // Display new cursor position
- graf_mouse(M_ON,NULL);
- }else{
- /* First, erase the current selection if there is one */
- if ((n->wtext.sel_start_line!=NULL)&&(n->wtext.sel_end_line!=NULL))
- {
- if ((n->wtext.sel_start_line!=n->wtext.sel_end_line)||(n->wtext.sel_start_char!=n->wtext.sel_end_char))
- {
- tl=n->wtext.display_baseline; f=FALSE;
- for(l=0; (l<n->wtext.display_lines_high)&&(tl->next!=NULL); tl=tl->next )
- {
- if ((tl==n->wtext.sel_start_line)||(tl==n->wtext.sel_end_line))
- f=TRUE;
- l++;
- }
- if (!f) // No selection markers found in display at all, check to see if whole display is selected
- {
- tl=n->wtext.sel_start_line;
- for(l=0; (l<n->wtext.display_lines_high)&&(tl->next!=NULL); tl=tl->next )
- {
- if (tl==n->wtext.display_baseline) // If we find the display baseline in the selected text, then the whole display is selected
- f=TRUE;
- l++;
- }
- }
- if (f)
- {
- graf_mouse(M_OFF,NULL);
- TW_display_highlighted(this_dialog, this_ob);
- graf_mouse(M_ON,NULL);
- }
- }
- }
-
- /* Now, find the start line for the new selected text */
- n->wtext.sel_start_line=n->wtext.display_baseline;
- for(l=0; (n->wtext.sel_start_line->next!=NULL)&&(l<y); l++)
- n->wtext.sel_start_line=n->wtext.sel_start_line->next;
-
- if (n->wtext.sel_start_line->next==NULL) y=l;
-
- if (x>n->wtext.sel_start_line->eof_line)
- {
- x=n->wtext.sel_start_char=n->wtext.sel_start_line->eof_line;
- }else
- n->wtext.sel_start_char=x;
-
- rx=x; ry=y;
- do
- {
- e=evnt_multi(MU_BUTTON|MU_M1,1,1,1,
- 1,lrl_x,lrl_y,1,1,
- 0,0,0,0,0,
- messB,1,0,&rl_x,&rl_y,&mb,&junk,&junk,&junk);
- graf_mkstate(&junk,&junk,&mb,&junk);
-
- if (e&MU_M1)
- {
- graf_mouse(M_OFF,NULL);
-
- if ((rx!=x)||(ry!=y)) // Erase the current highlight
- TW_display_highlighted(this_dialog, this_ob);
-
- rx=(rl_x-cr_clip.g_x-5)/cw;
- ry=(rl_y-cr_clip.g_y-5)/ch;
- if (ry<=y) // Can only mark forwards using this :(
- {
- ry=y;
- if (rx<x) rx=x;
- }
-
- tln_t=n->wtext.display_baseline; // Find the line containing the end marker
- for (l=0; (tln_t->next!=NULL)&&(l<ry); l++) tln_t=tln_t->next;
- n->wtext.sel_end_line=tln_t;
-
- if (tln_t->next==NULL) ry=l;
-
- if (rx>tln_t->eof_line) // Make sure we cann't select past eofline
- {
- rx=n->wtext.sel_end_char=tln_t->eof_line;
- }else
- n->wtext.sel_end_char=rx;
-
- if ((rx!=x)||(ry!=y)) // Display the new highlight
- TW_display_highlighted(this_dialog, this_ob);
-
- graf_mouse(M_ON,NULL);
- lrl_x=rl_x; lrl_y=rl_y;
- }
- } while (mb);
- }
- }
-
- return FALSE;
- }
-
- /*
- Copy selected text to the GEM clipboard
- */
- void TW_copy_text(short dialog, short object)
- {
- Elist *n;
- FILE *scrap_file;
- text_line *tt;
- text_line *tn;
- char p[FMSIZE+10];
- char *c, *tmp;
-
- if (find_event(dialog,object,&n))
- {
- sprintf(p,"%s%s",clipboard_path,"SCRAP.TXT");
- scrap_file=fopen(p,"w");
-
- if (scrap_file)
- {
- tmp=(char*)malloc(sizeof(char)*(n->wtext.max_columns+3));
- c=n->wtext.sel_start_line->the_text + n->wtext.sel_start_char;
- sprintf(tmp,"%s",c);
- if (n->wtext.sel_start_line==n->wtext.sel_end_line)
- tmp[n->wtext.sel_end_char - n->wtext.sel_start_char]='\0';
-
- fprintf(scrap_file,"%s\n",tmp);
-
- if (n->wtext.sel_start_line!=n->wtext.sel_end_line)
- {
- tt=n->wtext.sel_start_line->next; tn=n->wtext.sel_end_line;
- while (tt!=tn)
- {
- fprintf(scrap_file,"%s\n",tt->the_text);
- tt=tt->next;
- }
-
- sprintf(tmp,"%s",n->wtext.sel_end_line->the_text);
- tmp[n->wtext.sel_end_char]='\0';
- fprintf(scrap_file,"%s\n",tmp);
- }
- fclose(scrap_file);
-
- free(tmp);
- }else{
- form_alert(1,"[1][ ERROR: Cann't write to clipboard. ][ Bugger ]");
- }
- }else{
- form_alert(1,"[1][ ERROR: Cann't find text widget info. ][ Bugger ]");
- }
- }
-
- /*
- Cut selected text to the GEM clipboard
- */
- void TW_cut_text(short dialog, short object)
- {
- Elist *n;
- text_line *tl, *tln;
- char *tmp,*t1,*t2;
-
- TW_copy_text(dialog, object); // First, copy the text to the clipboard
-
- if (find_event(dialog, object,&n))
- {
- tmp=(char*)malloc(sizeof(char)*(n->wtext.max_columns+4));
- if (n->wtext.sel_start_line!=n->wtext.sel_end_line) // Delete text from first line
- {
- n->wtext.sel_start_line->the_text[n->wtext.sel_start_char]='\0';
- }else{
- sprintf(tmp,"%s",n->wtext.sel_start_line->the_text);
- t1=n->wtext.sel_start_line->the_text + n->wtext.sel_end_char;
- t2=tmp+n->wtext.sel_start_char;
- sprintf(t2,"%s",t1);
- sprintf(n->wtext.sel_start_line->the_text,"%s",tmp);
- }
- n->wtext.sel_start_line->eof_line=strlen(n->wtext.sel_start_line->the_text);
-
- if (n->wtext.sel_start_line!=n->wtext.sel_end_line) // Delete whole lines that are going
- {
- tl=n->wtext.sel_start_line->next;
- while (tl!=n->wtext.sel_end_line)
- {
- tln=tl->next;
- free(tl->the_text);
- free(tl);
- tl=tln;
- }
- n->wtext.sel_start_line->next=n->wtext.sel_end_line;
-
- t1=n->wtext.sel_end_line->the_text + n->wtext.sel_end_char; // Delete start of last line
- sprintf(tmp,"%s",t1);
- sprintf(n->wtext.sel_end_line->the_text,"%s",tmp);
- }
-
- n->wtext.sel_end_line=n->wtext.sel_start_line;
- n->wtext.sel_end_char=n->wtext.sel_start_char=0;
- free(tmp);
- }else{
- form_alert(1,"[1][ ERROR: Cann't find text widget info. ][ Bugger ]");
- }
-
- }
-
- /*
- The Text Widget Keyboard Handler
- The TWKH runs as an Object Layer key handler associated with text widget objects.
- This copes with all the standard text editting CTRL+key combo's, those which aren't
- recognised are dropped through to the Dialog Layer.
- All ALT+key combos are dropped through to the Dialog Layer.
-
- This is pretty messy - don't laugh, at least it works.
- */
- short TW_keypress(void)
- {
- Elist *n;
- text_line *tln_t;
- char c, *tmp;
- short p,f;
-
- if (!find_event(this_dialog,this_ob,&n))
- {
- form_alert(1,"[1][ ERROR: Cann't find text widget info. ][ Bugger ]");
- return FALSE;
- }
-
- if (kc_shstate&K_ALT) // Text widgets don't use ALT+key combo's
- return FALSE; // so let the key through to Dialog Layer.
-
- if (kc_shstate&K_CTRL) // Is control held down? If so, there may be a CTRL+key combo we want to know about.
- {
- switch (kc_key) // Do plain cursor & special key parsing
- {
- case 0x2e03: // ^C==Copy
- if ((n->wtext.sel_start_line!=n->wtext.sel_end_line)||(n->wtext.sel_start_char!=n->wtext.sel_end_char))
- {
- TW_copy_text(this_dialog, this_ob);
- }
- return TRUE;
- break;
- case 0x2d18: // ^X==Cut
- if ((n->wtext.sel_start_line!=n->wtext.sel_end_line)||(n->wtext.sel_start_char!=n->wtext.sel_end_char))
- {
- TW_cut_text(this_dialog, this_ob);
- graf_mouse(M_OFF,NULL);
- TW_display();
- graf_mouse(M_ON,NULL);
- }
- return TRUE;
- break;
-
- }
- return FALSE; // Allow any CTRL+key combo's that the text_widget doesn't understand fall through to the Dialog layer.
- }
-
- switch (kc_key) // Do plain cursor & special key parsing
- {
- case 0x4800: // Cursor up
- if (n->wtext.current_line->prev)
- {
- if (n->wtext.cursor_y)
- {
- graf_mouse(M_OFF,NULL);
- TW_display_cursor(this_dialog, this_ob);
- n->wtext.current_line=n->wtext.current_line->prev;
- n->wtext.cursor_y--;
- if (n->wtext.current_column>n->wtext.current_line->eof_line)
- n->wtext.current_column=n->wtext.current_line->eof_line;
- TW_display_cursor(this_dialog, this_ob);
- graf_mouse(M_ON,NULL);
- }else{
- n->wtext.display_baseline=n->wtext.current_line=n->wtext.current_line->prev;
- if (n->wtext.current_column>n->wtext.current_line->eof_line)
- n->wtext.current_column=n->wtext.current_line->eof_line;
- graf_mouse(M_OFF,NULL);
- TW_display();
- graf_mouse(M_ON,NULL);
- }
-
- }
- return TRUE; // Consume
- break;
- case 0x4838: // Shift+Cursor up
- for (f=0; (f<n->wtext.display_lines_high)&&(n->wtext.display_baseline->prev!=NULL); f++)
- {
- n->wtext.display_baseline=n->wtext.display_baseline->prev;
- n->wtext.current_line=n->wtext.current_line->prev;
- }
- if (n->wtext.current_column>n->wtext.current_line->eof_line)
- n->wtext.current_column=n->wtext.current_line->eof_line;
- graf_mouse(M_OFF,NULL);
- TW_display();
- graf_mouse(M_ON,NULL);
- return TRUE; // Consume
- break;
- case 0x5000: // Cursor down
- if (n->wtext.current_line->next)
- {
- if (n->wtext.cursor_y<n->wtext.display_lines_high-1)
- {
- graf_mouse(M_OFF,NULL);
- TW_display_cursor(this_dialog, this_ob);
- n->wtext.current_line=n->wtext.current_line->next;
- n->wtext.cursor_y++;
- if (n->wtext.current_column>n->wtext.current_line->eof_line)
- n->wtext.current_column=n->wtext.current_line->eof_line;
- TW_display_cursor(this_dialog, this_ob);
- graf_mouse(M_ON,NULL);
- }else{
- n->wtext.display_baseline=n->wtext.display_baseline->next;
- n->wtext.current_line=n->wtext.current_line->next;
- if (n->wtext.current_column>n->wtext.current_line->eof_line)
- n->wtext.current_column=n->wtext.current_line->eof_line;
- graf_mouse(M_OFF,NULL);
- TW_display();
- graf_mouse(M_ON,NULL);
- }
-
- }
- return TRUE; // Consume
- break;
- case 0x5032: // Shift+Cursor down
- for (f=0; (f<n->wtext.display_lines_high)&&(n->wtext.current_line->next!=NULL); f++)
- {
- n->wtext.display_baseline=n->wtext.display_baseline->next;
- n->wtext.current_line=n->wtext.current_line->next;
- }
- if (n->wtext.current_column>n->wtext.current_line->eof_line)
- n->wtext.current_column=n->wtext.current_line->eof_line;
- graf_mouse(M_OFF,NULL);
- TW_display();
- graf_mouse(M_ON,NULL);
- return TRUE; // Consume
- break;
- case 0x4d00: // Cursor right
- if (n->wtext.current_column<n->wtext.current_line->eof_line) // If we aren't at RHS, step right one character
- {
- graf_mouse(M_OFF,NULL);
- TW_display_cursor(this_dialog, this_ob);
- n->wtext.current_column++;
- TW_display_cursor(this_dialog, this_ob);
- graf_mouse(M_ON,NULL);
- }else{ // Otherwise, try to go to start of next line
- if (n->wtext.current_line->next)
- {
- if (n->wtext.cursor_y<n->wtext.display_lines_high-1)
- {
- graf_mouse(M_OFF,NULL);
- TW_display_cursor(this_dialog, this_ob);
- n->wtext.current_column=0;
- n->wtext.current_line=n->wtext.current_line->next;
- n->wtext.cursor_y++;
- TW_display_cursor(this_dialog, this_ob);
- graf_mouse(M_ON,NULL);
- }else{
- n->wtext.current_column=0;
- n->wtext.display_baseline=n->wtext.display_baseline->next;
- n->wtext.current_line=n->wtext.current_line->next;
- graf_mouse(M_OFF,NULL);
- TW_display();
- graf_mouse(M_ON,NULL);
- }
- }
- }
- return TRUE; // Consume
- break;
- case 0x4d36: // Shift+Cursor right
- if (n->wtext.current_column<n->wtext.current_line->eof_line)
- {
- n->wtext.current_column=n->wtext.current_line->eof_line;
-
- graf_mouse(M_OFF,NULL);
- TW_display();
- graf_mouse(M_ON,NULL);
- }
- return TRUE; // Consume
- break;
- case 0x4b00: // Cursor left
- if (n->wtext.current_column>0) // If we aren't at LHS, just step left
- {
- graf_mouse(M_OFF,NULL);
- TW_display_cursor(this_dialog, this_ob);
- n->wtext.current_column--;
- TW_display_cursor(this_dialog, this_ob);
- graf_mouse(M_ON,NULL);
- }else{ // Otherwise, try to go to EOF previous line
- if (n->wtext.current_line->prev)
- {
- if (n->wtext.cursor_y)
- {
- graf_mouse(M_OFF,NULL);
- TW_display_cursor(this_dialog, this_ob);
- n->wtext.current_line=n->wtext.current_line->prev;
- n->wtext.cursor_y--;
- n->wtext.current_column=n->wtext.current_line->eof_line;
- TW_display_cursor(this_dialog, this_ob);
- graf_mouse(M_ON,NULL);
- }else{
- n->wtext.display_baseline=n->wtext.current_line=n->wtext.current_line->prev;
- n->wtext.current_column=n->wtext.current_line->eof_line;
- graf_mouse(M_OFF,NULL);
- TW_display();
- graf_mouse(M_ON,NULL);
- }
- }
- }
- return TRUE; // Consume
- break;
- case 0x4b34: // Shift+Cursor left
- if (n->wtext.current_column>0)
- {
- n->wtext.current_column=0;
-
- graf_mouse(M_OFF,NULL);
- TW_display();
- graf_mouse(M_ON,NULL);
- }
- return TRUE; // Consume
- break;
- case 0x4700: // Clear home
- n->wtext.display_baseline=n->wtext.current_line=n->wtext.text;
- n->wtext.current_column=0;
- n->wtext.cursor_y=0;
- graf_mouse(M_OFF,NULL);
- TW_display();
- graf_mouse(M_ON,NULL);
- return TRUE; // Consume
- break;
- case 0x4737: // Shift+Clear Home == bottom of text
- for (; n->wtext.current_line->next!=NULL; )
- {
- n->wtext.display_baseline=n->wtext.display_baseline->next;
- n->wtext.current_line=n->wtext.current_line->next;
- }
- if (n->wtext.current_column>n->wtext.current_line->eof_line)
- n->wtext.current_column=n->wtext.current_line->eof_line;
- graf_mouse(M_OFF,NULL);
- TW_display();
- graf_mouse(M_ON,NULL);
- return TRUE; // Consume
- break;
- case 0x1c0d: // Enter inserts a new line
- tln_t=(text_line*)malloc(sizeof(text_line)); // Allocate a new line
- tln_t->the_text=(char*)malloc(sizeof(char)*n->wtext.max_columns); // Text store for the new line
- tln_t->the_text[0]='\0'; // Flag the text store as initially empty
-
- tln_t->next=n->wtext.current_line->next; // Slot the new line into the lines list for this widget
- n->wtext.current_line->next=tln_t;
- tln_t->prev=n->wtext.current_line;
- if (tln_t->next) tln_t->next->prev=tln_t; // If we aren't last line in the list, ensure the next line know where we are.
-
- if (n->wtext.current_column!=n->wtext.current_line->eof_line) // If not at end of line, move the rest of the current line onto a new line
- {
- tmp=n->wtext.current_line->the_text+(n->wtext.current_column);
- sprintf(tln_t->the_text,"%s",tmp);
- n->wtext.current_line->the_text[n->wtext.current_column]='\0';
- n->wtext.current_line->eof_line=n->wtext.current_column;
- }
- tln_t->eof_line=strlen(tln_t->the_text); // Where is end of line?
-
- n->wtext.current_line=tln_t; // Current line == the new line
-
- n->wtext.current_column=0; // Always begin with cursor at start of new line
-
- if (n->wtext.cursor_y<n->wtext.display_lines_high-1) // Insert a new line not at bottom of widget, move cursor down a line
- {
- n->wtext.cursor_y++;
- }else{ // Otherwise, scroll the whole widget up one line & leave cursor at same posistion
- n->wtext.display_baseline=n->wtext.display_baseline->next;
- }
-
- graf_mouse(M_OFF,NULL);
- TW_display();
- graf_mouse(M_ON,NULL);
- return TRUE; // Consume
- break;
- case 0x0e08: // Backspace
- if (n->wtext.current_column>0) // If we aren't at LHS, just copy over char directly to our left
- {
- for(p=n->wtext.current_column-1; p<n->wtext.current_line->eof_line; p++)
- n->wtext.current_line->the_text[p]=n->wtext.current_line->the_text[p+1];
-
- n->wtext.current_column--;
- n->wtext.current_line->eof_line--;
- n->wtext.current_line->the_text[n->wtext.current_line->eof_line]='\0';
-
- graf_mouse(M_OFF,NULL);
- TW_display();
- graf_mouse(M_ON,NULL);
- }else{ // Otherwise, try to go to EOF previous line
- if (n->wtext.current_line->prev)
- {
- if (n->wtext.current_line->eof_line+n->wtext.current_line->prev->eof_line < n->wtext.max_columns)
- {
- tln_t=n->wtext.current_line;
- tmp=tln_t->prev->the_text+(tln_t->prev->eof_line); // Tag line onto the end off previous line
- sprintf(tmp,"%s",tln_t->the_text);
- n->wtext.current_column=tln_t->prev->eof_line;
- tln_t->prev->eof_line=strlen(tln_t->prev->the_text);
- tln_t->prev->the_text[tln_t->prev->eof_line]='\0';
-
- tln_t->prev->next=tln_t->next; // detatch line from list
- if (tln_t->next)
- tln_t->next->prev=tln_t->prev;
-
- if (n->wtext.display_baseline==tln_t) n->wtext.display_baseline=n->wtext.current_line->prev;
- n->wtext.current_line=n->wtext.current_line->prev;
- free(tln_t->the_text); //free up the char array.
- free(tln_t); //free up the line structure
-
- if (n->wtext.cursor_y)
- n->wtext.cursor_y--;
-
- graf_mouse(M_OFF,NULL);
- TW_display();
- graf_mouse(M_ON,NULL);
- }
- }
- }
- return TRUE; // Consume
- break;
- case 0x537f: // Delete
- if (kc_shstate&(K_RSHIFT|K_LSHIFT)) // Shift Delete does delete line
- {
- tln_t=n->wtext.current_line;
- if (tln_t->prev)
- tln_t->prev->next=tln_t->next; // detatch line from list
- if (tln_t->next)
- tln_t->next->prev=tln_t->prev;
-
- if (tln_t->next) // If there is a next line, shift it up to be under the cursor
- {
- n->wtext.current_line=tln_t->next;
- }else{
- if (tln_t->prev) // Otherwise go back to previous line
- {
- n->wtext.current_line=tln_t->prev;
- if (n->wtext.cursor_y) // If not at top of widget, move cursor up a line.
- n->wtext.cursor_y--;
- }
- }
-
- if (n->wtext.display_baseline==tln_t) // If the baseline has been deleted, change it
- n->wtext.display_baseline=n->wtext.current_line;
-
- if (n->wtext.current_line!=tln_t) // If there are still lines left, free up the deleted lines storage
- {
- free(tln_t->the_text); //free up the char array.
- free(tln_t); //free up the line structure
- }else{ // Don't free the last line, just set it as empty otherwise there is nowhere to put characters that we type
- n->wtext.current_line->eof_line=0;
- n->wtext.current_line->the_text[0]='\0';
- }
-
- if (n->wtext.current_column>n->wtext.current_line->eof_line)
- n->wtext.current_column=n->wtext.current_line->eof_line;
-
- graf_mouse(M_OFF,NULL);
- TW_display();
- graf_mouse(M_ON,NULL);
-
- }else{ // Delete on it's own does delete char under cursor
- if (n->wtext.current_column<n->wtext.current_line->eof_line) // Not at end of line yet, so simply shuffle things back to erase current character.
- {
- for(p=n->wtext.current_column; p<n->wtext.current_line->eof_line; p++)
- n->wtext.current_line->the_text[p]=n->wtext.current_line->the_text[p+1];
-
- n->wtext.current_line->eof_line--;
- n->wtext.current_line->the_text[n->wtext.current_line->eof_line]='\0';
-
- graf_mouse(M_OFF,NULL);
- TW_display();
- graf_mouse(M_ON,NULL);
- }else{ // Otherwise, try to append next line to this one
- if (n->wtext.current_line->next)
- {
- if (n->wtext.current_line->eof_line+n->wtext.current_line->next->eof_line < n->wtext.max_columns)
- {
- tln_t=n->wtext.current_line->next;
- tmp=n->wtext.current_line->the_text+(n->wtext.current_line->eof_line); // Tag next line onto the end off this line
- sprintf(tmp,"%s",tln_t->the_text);
- n->wtext.current_line->eof_line=strlen(n->wtext.current_line->the_text);
- n->wtext.current_line->the_text[n->wtext.current_line->eof_line]='\0';
-
- n->wtext.current_line->next=tln_t->next; // detatch line from list
- if (tln_t->next)
- tln_t->next->prev=n->wtext.current_line;
-
- free(tln_t->the_text); //free up the char array.
- free(tln_t); //free up the line structure
-
- graf_mouse(M_OFF,NULL);
- TW_display();
- graf_mouse(M_ON,NULL);
- }
- }
- }
- }
- return TRUE;
- break;
- }
-
- // If we get to here, then we must just have a plain character typed.
-
- c=(char)(kc_key&255); // Convert scan code into ASCII character.
-
- if (n->wtext.current_line->eof_line<n->wtext.max_columns) // Insert character into line (if line isn't full).
- {
- if (n->wtext.current_column!=n->wtext.current_line->eof_line) // If not at end of line, insert a space for the character
- {
- for(p=n->wtext.current_line->eof_line; p>n->wtext.current_column; p--)
- n->wtext.current_line->the_text[p]=n->wtext.current_line->the_text[p-1];
- }
- n->wtext.current_line->the_text[n->wtext.current_column]=c;
- n->wtext.current_column++;
- n->wtext.current_line->eof_line++;
- n->wtext.current_line->the_text[n->wtext.current_line->eof_line]='\0';
-
- graf_mouse(M_OFF,NULL);
- TW_display();
- graf_mouse(M_ON,NULL);
- return TRUE; // Consume
- }
-
- return TRUE; // Consume
- }
-
-